import os, cv2, random
import numpy as np
import pandas as pd
from tqdm import tqdm
import matplotlib.pyplot as plt
from matplotlib import ticker
import seaborn as sns
%matplotlib inline
import keras
from keras.models import Sequential
from keras.layers import Input, Dropout, Flatten, Convolution2D, MaxPooling2D, Dense, Activation
from tensorflow.keras.optimizers import RMSprop
from keras.callbacks import ModelCheckpoint, Callback, EarlyStopping
from keras.utils import np_utils
from keras.applications.vgg16 import VGG16
from keras.models import Model
import warnings
warnings.filterwarnings('ignore')
# variables for model
ROWS = 224
COLS = 224
CHANNELS = 3
BATCH_SIZE = 16
STEPS_PER_EPOCH = 200
EPOCHS = 3
# directory containing all train images, the images are stored with names
# images of dogs are stored as dog.xx.jpg where xx is a number
# similarly for cats
# we use this to geenrate train data of cats and dogs
# also to generate train labels
TRAIN_DIR = os.path.join(os.getcwd(),'images')
# test dir contains images with no lables
# we use it for checking our model
TEST_DIR = os.path.join(os.getcwd(),'test_images')
print(os.listdir(TRAIN_DIR)[:5])
train_images = [TRAIN_DIR+i for i in os.listdir(TRAIN_DIR)] # use this for full dataset
train_dogs = [TRAIN_DIR+i for i in os.listdir(TRAIN_DIR) if 'dog' in i]
train_cats = [TRAIN_DIR+i for i in os.listdir(TRAIN_DIR) if 'cat' in i]
test_images = [TEST_DIR+i for i in os.listdir(TEST_DIR)]
# taking only 3000 images per class, for computation efficiency
train_images = train_dogs[0:3000] + train_cats[0:3000]
# shuffling data
random.shuffle(train_images)
# takin 5000 random images for testing
test_images = test_images[0:1000]
# function to read image file and resize to 224 x 224
def read_image(file_path):
img = cv2.imread(file_path, cv2.IMREAD_COLOR) #cv2.IMREAD_GRAYSCALE
return cv2.resize(img, (ROWS, COLS), interpolation=cv2.INTER_CUBIC)
# convert list of images to numpy array
def process_images(images):
data = []
for i in tqdm(images):
image = read_image(i)
data.append(image)
return np.array(data)
train = process_images(train_images)
test = process_images(test_images)
labels = []
for i in train_images:
if 'dog' in i.split('/')[-1]:
labels.append(1)
else:
labels.append(0)
print("Train shape: {}".format(train.shape))
print("Test shape: {}".format(test.shape))
sns.countplot(labels).set_title('Cats and Dogs')
labels = np.array(labels)
1%|▋ | 55/6000 [00:00<00:10, 546.37it/s]
['cat.12247.jpg', 'cat.12248.jpg', 'cat.12249.jpg', 'cat.1225.jpg', 'cat.12250.jpg']
100%|█████████████████████████████████████████████████████████████████████████████| 6000/6000 [00:12<00:00, 499.14it/s] 100%|█████████████████████████████████████████████████████████████████████████████| 1000/1000 [00:02<00:00, 491.55it/s]
Train shape: (6000, 224, 224, 3) Test shape: (1000, 224, 224, 3)
def show_images(idx):
cat = read_image(train_cats[idx])
dog = read_image(train_dogs[idx])
pair = np.concatenate((cat, dog), axis=1)
print(cat.shape)
plt.figure(figsize=(10,5))
plt.imshow(pair)
plt.show()
for i in np.random.randint(0, 6000, 5):
show_images(i)
(224, 224, 3)
(224, 224, 3)
(224, 224, 3)
(224, 224, 3)
(224, 224, 3)
vgg16 = VGG16(include_top = False, # drop top layers
weights = 'imagenet', # weights used in training imagenet
input_shape=(ROWS, COLS, 3))
vgg16.trainable = False # freezing the base model
inputs = keras.Input(shape=(ROWS, COLS, 3)) # defining the input layer
outputs = vgg16(inputs, training=False)
outputs = Flatten()(outputs)
outputs = Dense(1, activation ='sigmoid')(outputs)
model = Model(inputs=inputs, outputs = outputs)
model.summary()
Model: "model" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_2 (InputLayer) [(None, 224, 224, 3)] 0 _________________________________________________________________ vgg16 (Functional) (None, 7, 7, 512) 14714688 _________________________________________________________________ flatten (Flatten) (None, 25088) 0 _________________________________________________________________ dense (Dense) (None, 1) 25089 ================================================================= Total params: 14,739,777 Trainable params: 25,089 Non-trainable params: 14,714,688 _________________________________________________________________
model.compile(optimizer ='adam',
loss = 'binary_crossentropy',
metrics=['accuracy'])
model.fit(train, labels, batch_size=BATCH_SIZE, epochs=EPOCHS,
validation_split=0.2, verbose=1, shuffle=False)
Epoch 1/3 300/300 [==============================] - 53s 152ms/step - loss: 1.5922 - accuracy: 0.9402 - val_loss: 1.7345 - val_accuracy: 0.9642 Epoch 2/3 300/300 [==============================] - 46s 153ms/step - loss: 0.4238 - accuracy: 0.9848 - val_loss: 1.2425 - val_accuracy: 0.9700 Epoch 3/3 300/300 [==============================] - 46s 154ms/step - loss: 0.1807 - accuracy: 0.9917 - val_loss: 1.7452 - val_accuracy: 0.9692
<keras.callbacks.History at 0x1c5c3035160>
predictions = model.predict(test, verbose=1)
32/32 [==============================] - 15s 308ms/step
for i in np.random.randint(0, 1000, 20):
if predictions[i, 0] >= 0.5:
print('I am {:.2%} sure this is a Dog'.format(predictions[i][0]))
else:
print('I am {:.2%} sure this is a Cat'.format(1-predictions[i][0]))
plt.imshow(test[i])
plt.show()
I am 100.00% sure this is a Cat
I am 100.00% sure this is a Cat
I am 100.00% sure this is a Cat
I am 100.00% sure this is a Cat
I am 100.00% sure this is a Dog
I am 100.00% sure this is a Dog
I am 100.00% sure this is a Cat
I am 100.00% sure this is a Dog
I am 100.00% sure this is a Dog
I am 100.00% sure this is a Dog
I am 100.00% sure this is a Cat
I am 100.00% sure this is a Dog
I am 100.00% sure this is a Cat
I am 100.00% sure this is a Cat
I am 100.00% sure this is a Dog
I am 100.00% sure this is a Dog
I am 100.00% sure this is a Cat
I am 100.00% sure this is a Cat
I am 100.00% sure this is a Dog
I am 100.00% sure this is a Dog